#pragma once

#include "Contracts.h"
#include <vector>
#include "nef.h"
#include "IPartImportsSatisfied.h"

extern char SPECIAL_CONTRACT[];
extern char EXOTIC_CONTRACT[];

class ComponentManipulator
	: public nef::IPartImportsSatisfied
{
	friend nef::nef_traits<ComponentManipulator>;

	typedef std::vector<IMyComponent::Ptr> ComponentList;
	typedef std::shared_ptr<ComponentList> ComponentListPtr;

public:
	size_t AvailableNumberOfOperations() const;

	std::vector<std::string> CallAllOperations(const std::string &a, const std::string &b) const;

	virtual void OnImportsSatisfied();

private:
	void SetSpecialComponent(const IMyComponent::Ptr &cp);
	void SetExoticComponents(const ComponentListPtr &exoComps);


	ComponentList _components;
	ComponentListPtr _exoComps;
	IMyComponent::Ptr _specialComponent;
	ISeparator::Ptr _separator;
};

// Nef allows you to either specify imports both inside the class declaration as well as in the following traits class.
// The traits can be beneficial because they allow us to prevent nef from leaking into a specific type, which
// can be very useful if you cannot modify the type, but you would still like to power it with nef.
// 
// NOTE: In vc11, you cannot use the member pointer import types from within the type declaration. This apparently
// works in newer gcc releases, and MS refuses to admit that it's a problem
template<>
struct nef::nef_traits<ComponentManipulator>
{
	// Imports

	// Shows how you can you a member pointer to initialize a "many".
	// "many" currently only operates on vectors, but all you need to do to support other container types is 
	// create a new nef_import_... type and then create a partial specialization of nef_import_resolver<...> for that type
	typedef nef_import_many<ComponentManipulator, IMyComponent, &ComponentManipulator::_components> import0;

	// This shows the member function version of import many. Notice how the argument value is a shared pointer to the vector,
	// whereas the member version is not a shared pointer
	typedef nef_import_many_fn<ComponentManipulator, IMyComponent, &ComponentManipulator::SetExoticComponents, EXOTIC_CONTRACT> import1;

	// This shows how to use a member function setter. This also uses a non-default contract called SPECIAL_CONTRACT, and the value is not required
	typedef nef_import_fn<ComponentManipulator, IMyComponent, &ComponentManipulator::SetSpecialComponent, SPECIAL_CONTRACT, false> import2;

	// This shows the member pointer based import for a single value
	typedef nef_import<ComponentManipulator, ISeparator, &ComponentManipulator::_separator, EXOTIC_CONTRACT> import3;
};